package cn.com.bluemoon.daps.model.controller.api;

import cn.com.bluemoon.daps.api.model.RemoteDataModelService;
import cn.com.bluemoon.daps.common.constant.ServiceNameConstants.DapsApiModel;
import cn.com.bluemoon.daps.common.datascope.IgnorePermission;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.enums.BmStatus;
import cn.com.bluemoon.daps.model.dto.ModelInfos;
import cn.com.bluemoon.daps.model.entity.*;
import cn.com.bluemoon.daps.model.service.DapDataModelService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import reactor.util.function.Tuple4;

import javax.annotation.Nullable;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Api(tags = {"FeignClient服务-模型api接口"})
@RequestMapping(DapsApiModel.API_MODEL)
@RestController
@Slf4j
@IgnorePermission(name = "服务注册-模型")
public class DapDataModelServiceApi implements RemoteDataModelService {

    @Resource
    DapDataModelService dapDataModelService;

    @GetMapping("/{id}")
    public ResultBean<DapDataModel> getById(@PathVariable("id") String id) {
        LambdaQueryWrapper<DapDataModel> validWrapper = dapDataModelService.bmLambdaQuery()
                .eq(DapDataModel::getId, id)
                .ne(DapDataModel::getBmStatus, BmStatus.DELETE);
        return ResultBean.ok(dapDataModelService.getOne(validWrapper));
    }

    @GetMapping("/get/{systemId}")
    public List<DapDataModel> findBySystemId(@PathVariable("systemId") String systemId) {
        LambdaQueryWrapper<DapDataModel> where = dapDataModelService.bmLambdaQuery()
                .eq(DapDataModel::getSystemId, systemId);
        return dapDataModelService.list(where);
    }

    /**
     * 某个系统下已经被其他模型引用的数据源
     *
     * @param sysId
     * @return
     */
    @GetMapping("/model/{sysId}")
    public ResultBean<List<DapDataModel>> getModelList(@PathVariable("sysId") String sysId) {
        return ResultBean.ok(dapDataModelService.getModelListById(sysId));
    }

    /**
     * 查询系统是否被模型引用
     *
     * @param sysId
     * @return
     */
    @GetMapping("/isUse")
    public ResultBean<List<DapDataModel>> getModels(@RequestParam("sysId")
                                                    @ApiParam("模型id") String sysId) {
        List<DapDataModel> dapDataModels = dapDataModelService.getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapDataModel>().eq(DapDataModel::getSystemId, sysId)
                        .eq(DapDataModel::getBmStatus, BmStatus.ON.getCode()));
        return ResultBean.ok(dapDataModels);

    }

    /**
     * 根据系统id批量查询
     * @param systemIds
     * @return
     */
    @PostMapping("batch/List")
    public ResultBean<List<DapDataModel>> getBatchModel(@RequestBody List<String> systemIds){

        List<DapDataModel> dapDataModels = dapDataModelService.getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapDataModel>().in(DapDataModel::getSystemId, systemIds)
                .eq(DapDataModel::getBmStatus, BmStatus.ON.getCode()));
        return ResultBean.ok(dapDataModels);
    }


    @GetMapping("/queryModelInfos")
    @ApiOperation(value = "并行获取模型下的表、字段、索引、分区信息")
    @IgnorePermission(name = "并行获取模型下的表、字段、索引、分区信息")
    public ResultBean<ModelInfos> queryModelInfosByModelAndNewest(@RequestParam("modelId") String modelId, @RequestParam(value = "newest") Boolean newest) {
        Tuple4<List<DapDataModelTable>, List<DapDataModelTableField>, List<DapDataModelSubordinateKey>, List<DapDataModelTablePartition>> result = dapDataModelService.queryModelInfosByModelAndNewest(modelId, newest);
        ModelInfos infos = new ModelInfos();
        infos.setTables(result.getT1());
        infos.setFields(result.getT2());
        infos.setIndexes(result.getT3());
        infos.setPartitions(result.getT4());
        return ResultBean.ok(infos);
    }

    @Override
    public ResultBean<ModelInfos> queryModelInfosByModelAndNewestAndTableIds(String modelId, Boolean newest, @Nullable List<String> tableIds) {
        // null 获取全部 若为空则返回空
        if (tableIds == null) {
            return queryModelInfosByModelAndNewest(modelId, newest);
        }
        Set<String> tIds = new HashSet<>(tableIds);
        return queryModelInfosByModelAndNewest(modelId, newest)
                .convert(modelInfos -> {
                    modelInfos.setTables(modelInfos.getTables().stream().filter(t -> tIds.contains(t.getId())).collect(Collectors.toList()));
                    modelInfos.setFields(modelInfos.getFields().stream().filter(t -> tIds.contains(t.getModelTableId())).collect(Collectors.toList()));
                    modelInfos.setIndexes(modelInfos.getIndexes().stream().filter(t -> tIds.contains(t.getModelTableId())).collect(Collectors.toList()));
                    modelInfos.setPartitions(modelInfos.getPartitions().stream().filter(t -> tIds.contains(t.getModelTableId())).collect(Collectors.toList()));
                    return modelInfos;
                });
    }

    @GetMapping("/matchName")
    @ApiOperation(value = "模糊获取模型列表")
    public ResultBean<List<DapDataModel>> findAllOrFindLikeName(@RequestParam("modelName") String name) {
        List<DapDataModel> models = dapDataModelService.matchName(name);
        return ResultBean.ok(models);
    }

    @GetMapping("/get/bizLine/model")
    @ApiOperation(value = "查询业务线是否被模型引用")
    public ResultBean<Boolean> getBizLineModel(@RequestParam("bizId") Integer bizId) {
        List<DapDataModel> models = dapDataModelService.getBaseMapper().selectList(new LambdaQueryWrapper<DapDataModel>().
                        eq(DapDataModel::getBmStatus, BmStatus.ON.getCode()).eq(DapDataModel::getBusinessLine, bizId));
        return ResultBean.ok(models.isEmpty());
    }
}
